跳到主要内容

C++11 Lambda表达式重载

一个有关C ++中lambda表达式重载的巧妙技巧。

在C ++ 11中,可以通过创建一个辅助函数对象类来重载lambda表达式,该类从编译器为lambda表达式生成的函数对象继承,然后通过使用声明引入lambda表达式的operator()。

这是一个简单的控制台应用程序,它针对两个lambda表达式进行了演示:

#include <iostream>

template <class F1, class F2>
struct overload_set : F1, F2 {
overload_set(F1 f1, F2 f2)
: F1(f1), F2(f2)
{}

using F1::operator();
using F2::operator();
};

template <class F1, class F2>
overload_set<F1, F2> overload(F1 f1, F2 f2)
{
return overload_set<F1, F2>(f1, f2);
}

int main(int argc, const char* argv[])
{
auto f = overload
(
[]() { return 1; },
[](int x) { return x + 1; }
);

int x = f();
int y = f(2);

std::cout << "x = " << x << ", y = " << y << std::endl;

return 0;
}

在此示例中,overload函数返回一个名为overload_set的函数对象,该对象从编译器为传递给它的两个lambda表达式创建的两个函数对象中继承。 请注意,您不一定必须使用lambda表达式。 可以使用任何公开operator()的函数对象类。

然后,通过using声明将这两个operator()放入overload_set。 因此,客户端代码现在可以看到一个函数对象类,该类提供了两个operator(),在这种情况下,一个没有参数,而另一个则带有整数参数。 通过函数对象进行调用时,常规函数重载会起作用,编译器会根据提供的参数选择正确的函数进行调用。

可变参数模板的实现

这是上述使用可变参数模板的技术的更一般的实现。

template <class... Fs> struct overload_set;

template <class F1, class... Fs>
struct overload_set<F1, Fs...> : F1, overload_set<Fs...>::type
{
typedef overload_set type;

overload_set(F1 head, Fs... tail)
: F1(head), overload_set<Fs...>::type(tail...)
{}

using F1::operator();
using overload_set<Fs...>::type::operator();
};

template <class F>
struct overload_set<F> : F
{
typedef F type;
using F::operator();
};

template <class... Fs>
typename overload_set<Fs...>::type overload(Fs... x)
{
return overload_set<Fs...>(x...);
}

这是一个很巧妙的技巧,即使可以承认它可能不会经常使用。 对于某些通用算法,例如实现编译时重载,可能会派上用场。